package com.wdb.common.util;

import com.google.common.collect.Lists;
import com.wdb.common.constant.Constant;
import org.apache.commons.beanutils.BeanUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;

public abstract class ConvertUtils {
    /**
     * convert source to target
     */
    public static <T> T convert(Class<T> destClass, Object src) {
        try {
            T dest = destClass.newInstance();
            BeanUtils.copyProperties(dest, src);
            return dest;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(Constant.Error.ERROR_SERVER);
        }
    }

    /**
     * convert object to map
     */
    public static Map<String, Object> convert(Object obj) {
        Map<String, Object> map = new HashMap<>();
        if (Objects.isNull(obj)) {
            return map;
        }
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            if (Objects.isNull(propertyDescriptors)) return map;
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                if (key.compareToIgnoreCase("class") == 0) {
                    continue;
                }
                Method getter = property.getReadMethod();
                Object value = Objects.nonNull(getter) ? getter.invoke(obj) : null;
                map.put(key, value);
            }
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(Constant.Error.ERROR_SERVER);
        }
    }

    /**
     * convert iterable to list
     */
    public static <S, T> List<T> convertList(final Class<T> targetClass, final Iterable<? extends S> iterable) {
        if (Objects.isNull(iterable)) {
            throw new RuntimeException(Constant.Error.ERROR_SERVER);
        }

        return Lists.newArrayList(new Iterator<T>() {
            private final Iterator<? extends S> iterator = iterable.iterator();

            @Override
            public boolean hasNext() {
                return iterator.hasNext();
            }

            @Override
            public T next() {
                return ConvertUtils.convert(targetClass,iterator.next());
            }
        });
    }

    /**
     * convert object to map <String,String></>
     */
    public static Map<String, String> stringify(Object obj) {
        Map<String, String> map = new HashMap<>();
        if (Objects.isNull(obj)) {
            return map;
        }
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            if (Objects.isNull(propertyDescriptors)) return map;
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                if (key.compareToIgnoreCase("class") == 0) {
                    continue;
                }
                Method getter = property.getReadMethod();
                Object value = Objects.nonNull(getter) ? getter.invoke(obj) : null;
                if (Objects.isNull(value)) {
                    continue;
                }
                map.put(key, value.toString());
            }
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(Constant.Error.ERROR_SERVER);
        }
    }
}
